package effectiveJava.innerClass;

import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * Created by dycong on 2017/9/2.
 * todo 嵌套类：静态成员类，非静态成员类，匿名类，局部类，后三种称为内部类；
 */
public class Car {
    private String logo;
    private double price;
    private String color;
    private static int age;

    /*todo 静态成员类,只能访问外围类的静态域，静态成员类与其他静态域相同，遵守同样的规则，静态成员类可以脱离外围类实例单独存在
    *todo 常见用法是作为共有的辅助类，仅当与它的外部类一起使用时才有意义，例如Map.Entry
    *todo 当成员嵌套类不需要引用外围类的非静态域(实例域)时，则使用静态成员类，因为非静态成员类即使不需要使用外围类的实例域依然需要一个指向外围类实例的引用，浪费时间空间*/
    static class Jaguar {
        private String city;
        private int subAge;

        public Jaguar() {
            city = "someWhere";
            subAge = age;
        }
    }

    /*todo 非静态成员类，可以反问外围实例的静态域，非静态域，必须与一个外围实例同时存在
     *todo 常见用法是定义一个Adapter,它允许外部类的实例被看作是另一个不相关的类的实例。例如，Map接口的实现往往用非静态成员类来实现他们的集合视图
     *todo 这些集合视图是由Map 的 keySet,entrySet,Values方法返回的，同样的Set/List迭代器也是通过非静态成员类实现的*/
    class BMW {
        private double subPrice;
        private int subAge;

        /*非静态成员类不可有静态成员*/
        public BMW() {
            this.subPrice = price;
            subAge = age;
        }
    }

    /*todo 匿名类可以出现在代码中任何可以出现表达式的地方，常见用法
    * 1. 动态的创建函数对象，例如Comparator<E>
    * 2. 穿件过程对象例如 Runnable*/
    public void sort(List<Car> c) {

        Collections.sort(c, new Comparator<Car>() {
            /*todo 匿todo 名类居然可以有成员，但不能包含静态成员*/
            private int age = 0;

            @Override
            public int compare(Car o1, Car o2) {
                age = 20;
                return 0;
            }
        });
    }

    /*todo 此处也是匿名类，匿名类是指没有类名，而不是不可有指向其实例的变量名*/
    private static Runnable runnable = new Runnable() {
        @Override
        public void run() {

        }
    };

    /*todo 局部类:在任何可以出现局部变量的的地方，都可以声明局部类，并且遵守和局部类相同的作用域*/
    public void run() {
        final int k = 0;
        String k2 = "";     /*todo 编译器隐式的 final 声明*/
        class Cadillac {
            /*todo 局部类不可有静态成员*/
            String city;

            public void start() {
                city = logo;
                System.out.println(k);
                System.out.println(k2);
            }
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(k);
                System.out.println(k2);
                ;
            }
        });
    }
}
